package fm.realm;

import com.alibaba.fastjson.JSON;
import fm.cache.RoleCache;
import fm.entity.PublicNumber;
import fm.entity.WxUser;
import fm.service.PublicNumberService;
import fm.service.UserService;
import fm.token.WeChatToken;
import fm.util.CacheUtils;
import fm.util.CommonUtils;
import fm.util.Constant;
import fm.util.PropertiesLoader;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created by CM on 2015/9/3.
 */
public class WechatRealm extends AuthorizingRealm {
    private static Logger log = LoggerFactory.getLogger(WechatRealm.class);

    @Autowired
    protected UserService userService;
    @Autowired
    private PublicNumberService publicNumberService;
    @Autowired
    HttpSession session;


  

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String uuid = (String) principalCollection.getPrimaryPrincipal();
        log.info("checking authorization information : {}", principalCollection.getPrimaryPrincipal());
        PublicNumber pbInfo = publicNumberService.getByUuid(uuid);
        List<String> roles = new ArrayList<String>();
        if (CommonUtils.isEmpty(pbInfo)) {
            roles.add(RoleCache.getPermision("WX_VISITOR"));
            log.info("checking authorization failed,public number not founded! : {}", principalCollection.getPrimaryPrincipal());
        } else {
            roles.add(RoleCache.getPermision("WX_SERVEICE_USER"));
            log.info("authorization finnish ,user roles : {}", JSON.toJSONString(roles));
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        log.info("authorization finish ,info: {}", JSON.toJSONString(info));
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws
            AuthenticationException {
        WeChatToken token = (WeChatToken) authenticationToken;
        log.info("do get authentication info,token:{}", token.toString());
        PublicNumber pnInfo = publicNumberService.getByUuid(token.getUuid());
        if (CommonUtils.isEmpty(pnInfo)) {
            //未找到公众号，不允许访问
            log.error("Wechat Public Number information  not found in the server database : {}!", token);
            throw new UnknownAccountException();
        }
        WxUser user = userService.getByOpenIdAndUuid(token.getOpenId(), token.getUuid());
        user.setOpenid(token.getOpenId());
        if (CommonUtils.isEmpty(user)) {
            log.info("Authentication finish, user information query failed,query user information from tencent!");
            throw new UnknownAccountException("用户信息尚未拉取，授权失败!");
        }
        session.setAttribute(Constant.SESSION_LOGIN_USER, user);
        session.setAttribute(Constant.SESSION_PUBLIC_NUMBER, pnInfo);
        log.info("Authentication finish, user:{} , public number:{}", user.getNickname(), pnInfo.getUuid());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(pnInfo.getUuid(), user.getOpenid(), getName());
        return info;
    }

    /**
     * 添加token支持
     *
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        if (token instanceof WeChatToken) {
            log.error("wechat authentication token! support!");
            return true;
        } else {
            log.error("unknown authentication token!");
            return super.supports(token);
        }
    }


}
